package com.kitty.game.difushidao.service;

import com.kitty.common.utils.DecodeSendMessage;
import com.kitty.common.utils.SpringUtils;
import com.kitty.game.ServerService;
import com.kitty.game.activity.service.ActivityHandler;
import com.kitty.game.chat.service.ChatService;
import com.kitty.game.difushidao.RespDiFuShidaoScore;
import com.kitty.game.difushidao.controller.DiFuShiDaoController;
import com.kitty.game.difushidao.domin.DiFuShiDaoPKData;
import com.kitty.game.difushidao.domin.TeamData;
import com.kitty.game.enter.ReqTelePort;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.fight.bean.Fight;
import com.kitty.game.fight.bean.FightObject;
import com.kitty.game.fight.factory.FightFactory;
import com.kitty.game.fight.service.FightExecutorService;
import com.kitty.game.fight.service.FightService;
import com.kitty.game.mail.model.Mail;
import com.kitty.game.rank.model.Range;
import com.kitty.game.role.model.Role;
import com.kitty.game.role.service.RoleService;
import com.kitty.game.team.model.Member;
import com.kitty.game.team.model.Team;
import com.kitty.game.team.service.TeamService;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.TimeUtil;
import com.kitty.listener.event.FightEndEvent;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.message.MessagePusher;
import com.kitty.mina.task.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class DiFuShiDaoPKService extends ActivityHandler {
    @Autowired
    protected TeamService teamService;
    @Autowired
    DiFuShiDaoService diFuShiDaoService;


    @Autowired
    RoleService roleService;
    @Autowired
    ServerService serverService;
    private static int winScore = 100;
    private static int failScore = 20;
    private int MAPID = 60007;
    private int MAP_X = 41;
    private int MAP_Y = 31;

    private static final int EXIT_MAPID = 60000;
    private static final int EXIT_X = 130;
    private static final int EXIT_Y = 40;
    @Autowired
    ChatService chatService;

    /**key: roleID, value: 对应角色在地府试道中的临时信息 */
    public static  Map<Integer, DiFuShiDaoPKData> pkRoleinfo = new ConcurrentHashMap<>();


    /**初始化地府试道*/
    public void start() {
        //表示可以匹配
        //地府试道大会开始。状态改为2

        DataCache.REDIS_DATA.put("difushidao_status","2");
        String notice = "本次地府竞技大赛正式开始，请各位道友游戏右侧选择开始匹配战斗，竞技场匹配期间请不要离队，离队会被直接传送出去导致没有奖励！#51 #82";
        chatService.sendAdnotice(notice);
    }
    /**初始化地府试道*/
    public void end() {
        //地府试道大会开始。状态改为1
        DataCache.REDIS_DATA.put("difushidao_status","0");
        //结束所有地府竞技场内的战斗
        quiteFight();
        //获取发送奖励 队伍信息
        Map<String,List<TeamData>> roleByLvRange = new HashMap<>();
        for (Map.Entry<Integer, DiFuShiDaoPKData> entry : pkRoleinfo.entrySet()) {
            log.info("地府竞技大赛预结算总人数数量："+pkRoleinfo.size());
            Role role = SpringUtils.getRoleService().getOnlinePlayer(entry.getKey());
            MessagePusher.pushMessage(role, new RespNotifyMiscEx("竞技大赛奖励已经发送到#R邮件#n，请注意领取。"));
            if(teamService.isTeamLeader(role)){
                String levelRange = DiFuShiDaoService.getLevelRange(role);
                List<TeamData> list  ;
                if(roleByLvRange.containsKey(levelRange)){
                    list = roleByLvRange.get(levelRange);
                }else{
                    list = new ArrayList<>();
                }
                Team team = teamService.getTeam(entry.getKey());
                TeamData teamData = new TeamData();
                teamData.setTeamScore(entry.getValue().getTotalScore());
                teamData.setTeam(team);
                list.add(teamData);
                roleByLvRange.put(levelRange,list);
            }
        }
        //踢出所有地图中的玩家
        for (Map.Entry<Integer, DiFuShiDaoPKData> longDiFuShiDaoPKDataEntry : this.pkRoleinfo.entrySet()) {
            int key = longDiFuShiDaoPKDataEntry.getKey();
            Role role = SpringUtils.getRoleService().getOnlinePlayer(key);
            if(!isInDiFuShiDaoMap(role)){
                continue;
            }
            if(teamService.isInTeam(role)){
                Team team = teamService.getTeam(role.getRoleId());
                Role leaderRole = SpringUtils.getRoleService().getOnlinePlayer(team.getLeaderUid());
                diFuShiDaoService.leaveDiFuShiDaoMap(leaderRole);
            }else{
                diFuShiDaoService.leaveDiFuShiDaoMap(role);
            }
        }

        //获取所有阶段 积分信息 结算奖励。
        for (Map.Entry<String, List<TeamData>> stringListEntry : roleByLvRange.entrySet()) {
            log.info("地府竞技大赛结算"+stringListEntry.getKey()+"段，队伍数量："+ stringListEntry.getValue().size());
            List<TeamData> teamList = stringListEntry.getValue();
            //排序
            teamList.sort(Comparator.comparing(TeamData::getTeamScore).reversed());
            //发送奖励。
            for (int j = 1; j <= teamList.size(); j++) {
                TeamData teamData = teamList.get(j-1);
                try{
                    //发送奖励  排名奖励
                    sendDiFuShiDaoReward(teamData,j);
                }catch(Exception e){
                    log.info("地府竞技大赛结算失败，"+teamData.getTeam().getMemberNames()+"出现异常：{}",e);
                }
            }
        }
    }

    public static final String REWARD_CONTENT = "#Y{0}#n赢得了#Y{1}#n的#Y{2}#n级别地府竞技大赛#R第{3}名#n，获得了{4}海量的奖励！";
    public void sendDiFuShiDaoReward(TeamData pkData,int rank){
        String name = "第"+rank+"名";

        if(rank > 3){
            name = "参与";
            rank = 4;
        }
        Team team = pkData.getTeam();
        for (Member member : team.getList()) {
            Role memberRole = roleService.getPlayerBy(member.getUid());
            StringBuilder rewardDesc = new StringBuilder();
            if(memberRole !=null && member.isInTeam()){
                //发送奖励
                Mail mail = SpringUtils.getMailService().createMail("地府竞技"+name+"奖励", "地府竞技奖励", 7 * TimeUtil.ONE_DAY);
                ArrayList<NutMap> maps = new ArrayList<>();
                String reward = DataCache.REDIS_DATA.get("difushidao_reward_"+rank);
                if(StringUtils.isNotEmpty(reward)){
                    for (String s : reward.split("\\+")) {
                        NutMap nutMap = DecodeSendMessage.buildSendRewardMessage(s);
                        if(Const.rewardJinyuanbao == nutMap.getInt("type",0)){
                            int amount = Integer.parseInt(s.split("-")[1]);
                            rewardDesc.append("#R"+amount+"元宝");
                        }
                        maps.add(nutMap);
                    }
                    mail.getDatas().addAll(maps);
                    SpringUtils.getMailService().sendNewMail(memberRole, mail);
                }
                if(rank <=3){
                    /**发系统消息*/
                    String roleName = memberRole.getName();
                    String dateStr = TimeUtil.formatDate(new Date(), "yyyy年MM月dd日");
                    String levelRange = getLevelRange(DiFuShiDaoService.getRange(Short.parseShort(String.valueOf(memberRole.getLevel()))));
                    String rankChinese = Const.ORDER_CHINESE.get((int) rank);
                    String content = MessageFormat.format(REWARD_CONTENT, roleName, dateStr, levelRange, rankChinese, rewardDesc);
                    SpringUtils.getChatService().sendSystem(content, Const.BRODCAST_MSG_TYPE_ROLE);
                }
            }
        }
    }

    public String getLevelRange(Range range) {
        return range.getMin() + "-" + range.getMax();
    }

    //地府竞技场退出战斗
    public void quiteFight(){
        ConcurrentHashMap<Integer, Fight> fights = FightExecutorService.FIGHTS;
        FightService bean = SpringUtils.getBean(FightService.class);
        for (Map.Entry<Integer, Fight> integerFightEntry : fights.entrySet()) {
            Fight fight = integerFightEntry.getValue();
            boolean isquite = false;
            try{
                for (FightObject fightObject : fight.getAllFightObjects()) {
                    Role tempRole = fightObject.getRole();
                    if (tempRole == null){
                        break;
                    }
                    //60007
                    if(isInDiFuShiDaoMap(tempRole)){
                        isquite = true;
                        bean.quiteFight(fight, fightObject, false);
                    }
                }
                if(isquite){
                    bean.clearFight(fight);
                }
            }catch(Exception e){
                log.info("地府竞技场结束战斗出错{}",e);
            }
        }
    }

    /**
     * 每个30S 扫描一下 每个等级的 地府竞技队伍
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void doPiPeiFight() {
        Map<String, Set<Team>> piPeiQueByLevel = DiFuShiDaoController.piPeiQueByLevel;
        for (Map.Entry<String, Set<Team>> shortListEntry : piPeiQueByLevel.entrySet()) {
            // 遍历每个 阶段的所有队伍。 进入战斗。   70-79，80-89
            Set<Team> teams = shortListEntry.getValue();
            log.info("当前扫描等级："+shortListEntry.getKey()+"队伍数量："+teams.size());
            randomTwoTeamGoFight(teams);
        }
    }
    public void randomTwoTeamGoFight(Set<Team> teams){
        ArrayList<Team> teamList = new ArrayList<>();
        Iterator<Team> iterator = teams.iterator();
        while(iterator.hasNext()){
            Team next = iterator.next();
            teamList.add(next);
        }



        int teamSize = teamList.size()/2;
        for (int i = 0; i < teamSize; i++) {
            int randomA = new Random().nextInt(teamList.size());
            Team teamA = teamList.get(randomA);
            int randomB = new Random().nextInt(teamList.size());
            while (randomA == randomB){
                randomB = new Random().nextInt(teamList.size());
            }
            Team teamB = teamList.get(randomB);
            if(teamA != null && teamB !=null){
                doStartFight(teamA,teamB);
                if(randomA > randomB){
                    teamList.remove(randomA);
                    teamList.remove(randomB);
                }else{
                    teamList.remove(randomB);
                    teamList.remove(randomA);
                }
                teams.remove(teamA);
                teams.remove(teamB);
            }
        }
    }

    /**
     * 进入战斗
     * @param teamA
     * @param teamB
     */
    public void doStartFight(Team teamA, Team teamB) {
        int mapId = Const.DIFU_SHIDAO_MAPID;
        int fightType = Const.fightType_month_shidao_pk;
        Fight fight = FightFactory.getFightFactory(fightType).create(mapId, fightType, teamA.getList(), teamB.getList());
        fight.setMaxRound(150);
        fight.start();
    }

    @Override
    public void handleFightEnd(FightEndEvent fightEndEvent) {
        /**事件应该是在战斗线程触发的，在玩家线程中处理玩家逻辑*/
        ThreadLocalUtil.addLocalTask(fightEndEvent.getRole(), () -> doFightEnd(fightEndEvent.getRole(), fightEndEvent));
    }

    /**
     * 战斗结束
     * @param role
     * @param fightEndEvent
     */
    public void doFightEnd(Role role, FightEndEvent fightEndEvent) {
        /**在组队又不是队长时返回*/
        if (!(fightEndEvent.getFightType() ==  Const.fightType_month_shidao_pk)) {
            return ;
        }
        if (role.getPos().getMapId() != Const.DIFU_SHIDAO_MAPID) {
            return ;
        }
        log.info("队伍："+role.getName());
        String difushidao_status = DataCache.REDIS_DATA.get("difushidao_status").toString();
        if("2".equals(difushidao_status)){
            if (fightEndEvent.getStatus() == FightEndEvent.WIN) {
                doFightReward(role,winScore);
            } else{
                doFightReward(role,failScore);
            }
        }

    }

    /**
     * 发送奖励
     * @param role
     * @param score
     */
    private void doFightReward( Role role,int score) {
        Team team = teamService.getTeam(role.getRoleId());
        ArrayList<Member> arrayList = new ArrayList<>(team.getList());
        for (Member member : arrayList) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            if (tempRole == null){
                continue;
            }
            addScore(tempRole,score);
        }
        for (Member member : arrayList) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            // 重置竞技场面板
            sendRespShidaoScore(tempRole,1);
        }
        for (Member member : arrayList) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            if(teamService.isTeamLeader(tempRole)){
                //重新加入匹配队列
                String levelRange = diFuShiDaoService.getLevelRange(tempRole);
                Set<Team> teamSet = DiFuShiDaoController.piPeiQueByLevel.get(levelRange);
                teamSet.add(team);
            }
        }


    }

    /**
     * 增加积分
     * @param role
     * @param score
     */
    private void addScore(Role role,int score) {
        /**增加试道积分*/
        if(pkRoleinfo.containsKey(role.getRoleId())){
            DiFuShiDaoPKData diFuShiDaoPKData = this.pkRoleinfo.get(role.getRoleId());
            diFuShiDaoPKData.setTotalScore(diFuShiDaoPKData.getTotalScore()+score);
            diFuShiDaoPKData.setProtectTime((int)System.currentTimeMillis()/1000);
            diFuShiDaoPKData.setFightNum(diFuShiDaoPKData.getFightNum()+1);
            log.info("({})增加地府试道积分：{}, 总积分: {}", role.getName(), score,diFuShiDaoPKData.getTotalScore());
        }
    }

    /**
     * 发送地府面板包
     * @param role
     * @param state
     */
    public void sendRespShidaoScore(Role role,int state) {
        int score = 0;
        int teamScore = 0;
        int teamCount = 0;
        int protectTime = 0;
        Map<Integer, DiFuShiDaoPKData> pkDataByLevel = this.pkRoleinfo;
        if(pkDataByLevel.containsKey(role.getRoleId())){
            score = pkDataByLevel.get(role.getRoleId()).getTotalScore();
            protectTime =  pkDataByLevel.get(role.getRoleId()).getProtectTime();
            if(teamService.isInTeam(role)){
                Team team = teamService.getTeam(role.getRoleId());
                teamScore = this.getTeamAvgScore(team.getList());
                teamCount = team.getList().size();
            }else{
                teamCount = 1;
            }
        }
        RespDiFuShidaoScore respShidaoScore = new RespDiFuShidaoScore();
        respShidaoScore.setMinLevel((byte)0);
        respShidaoScore.setMaxLevel((byte)200);
        respShidaoScore.setIsMatching((byte)state);
        respShidaoScore.setProtectTime(protectTime);
        respShidaoScore.setTeamScore(teamScore);
        respShidaoScore.setScore(score);
        respShidaoScore.setTeamMembersCount((byte)teamCount);

        Long start = DiFuShiDaoService.shiDaoData.getStartTime().getTimeInMillis()/ 1000;
        respShidaoScore.setMatchStartTime(start.intValue());

        int time = Integer.parseInt(DataCache.REDIS_DATA.get("difushidao_fighttime"));
        Long end  = start + ( time * 60);
        respShidaoScore.setMatchEndTime(end.intValue());
        MessagePusher.pushMessage(role, respShidaoScore);
    }

    public static void main(String[] args) {
        Calendar calendar =  Calendar.getInstance();
        System.out.println(calendar.getTimeInMillis());

        System.out.println(new Date().getTime() / 1000);
    }

    /**
     * 在地府世道中 离开队伍 逻辑
     */
    public void doAfterLeaveTeam(Role role, Team team){
        if (!isInDiFuShiDaoMap(role)) {
            return;
        }
        Role leaderRole = SpringUtils.getRoleService().getOnlinePlayer(team.getLeaderRoleId());
        if(leaderRole == null){
            leaderRole = role;
        }
        //队伍变更移除匹配信息。
        String levelRange = diFuShiDaoService.getLevelRange(leaderRole);
        Set<Team> teamSet = DiFuShiDaoController.piPeiQueByLevel.get(levelRange);
        if(teamSet != null && teamSet.contains(team)){
            teamSet.remove(team);
        }
        for (Member member : team.getList()) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            sendRespShidaoScore(tempRole,0);
        }
        sendRespShidaoScore(role,0);

        /**不需要检测能否切换地图*/
        role.pushTempCache(Const.NOT_CHECK_CHANGE_MAP, true);
        //踢出地府竞技场地图;
        ReqTelePort reqTelePort = new ReqTelePort();
        reqTelePort.setMapId(EXIT_MAPID);
        reqTelePort.setX(EXIT_X);
        reqTelePort.setY(EXIT_Y);
        SpringUtils.getMapService().changeMap(role, reqTelePort);

        if(pkRoleinfo.containsKey(role.getRoleId())){
            pkRoleinfo.remove(role.getRoleId());
        }
    }

    public void leaveDiFuShiDaoMap(Role role) {

    }
    /**
     * 在地府世道中 加入队伍 逻辑
     */
    public void doAfterAddTeam(Role role, Team team){
        if (!isInDiFuShiDaoMap(role)) {
            return;
        }
        Role leaderRole = SpringUtils.getRoleService().getOnlinePlayer(team.getLeaderRoleId());
        //队伍变更移除匹配信息。
        String levelRange = diFuShiDaoService.getLevelRange(leaderRole);
        Set<Team> teamSet = DiFuShiDaoController.piPeiQueByLevel.get(levelRange);
        if(teamSet != null && teamSet.contains(team)){
            teamSet.remove(team);
        }
        for (Member member : team.getList()) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            sendRespShidaoScore(tempRole,0);
        }
    }
    /**
     * 获取当前人队伍平均积分
     * @param
     * @return
     */
    public int getTeamAvgScore(ArrayList<Member> Members){
        int scoreSum = 0;
        for (Member member : Members) {
            Role tempRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
            if (tempRole == null){
                continue;
            }
            Map<Integer, DiFuShiDaoPKData> pkDataByLevel = this.pkRoleinfo;
            if(pkDataByLevel.containsKey(tempRole.getRoleId())){
               int  roleScore = pkDataByLevel.get(tempRole.getRoleId()).getTotalScore();
                scoreSum += roleScore;
            }
        }
        if(scoreSum>0){
            return scoreSum/Members.size();
        }else{
            return 0;
        }
    }
    /**
     * 是否在竞技场
     */
    public boolean isInDiFuShiDaoMap(Role role) {
        return SpringUtils.getMapService().isInMap(role, MAPID);
    }


}
